<?php

class JCAT_DBIdentity
	implements JCAT_IIdentity
{
	const ID_CLASS = '::UserIdentity' ;
	
	/**
	 * 
	 *@access public 
	 *@param $aDBModel									JCAT_IDBModel
	 *@return void 
	 */
	public function JCAT_DBIdentity (JCAT_IDBModel $aDBModel,$sPurviewProperty=null)
	{
		$this->aDBModel = $aDBModel ;
		$this->SetPurviewProperty($sPurviewProperty) ;
	}
	
	/**
	 * 返回 数据库模型
	 *
	 * @access	public
	 * @return	JCAT_DBModel
	 */
	public function GetModel()
	{
		return $this->aDBModel ;
	}
	
	/**
	 * 取得 用户 的 UserID
	 *
	 * @access	public
	 * @return	string
	 */
	public function GetUserId()
	{
		return $this->aDBModel->GetId() ;
	}
	
	/**
	 * 取得身份类型
	 *
	 * @access	public
	 * @return	string
	 */
	public function GetIdentityClass()
	{
		return self::ID_CLASS ;
	}
	
	/**
	 * what's this
	 * 
	 * @access	public
	 * @return	void
	 */
	public function __sleep()
	{
		$arrParentPropertys[] = JCAT_Package::MakePrivatePropertyNameForSerialize('aDBModel',__CLASS__) ;
		$arrParentPropertys[] = JCAT_Package::MakePrivatePropertyNameForSerialize('bLogined',__CLASS__) ;
		$arrParentPropertys[] = JCAT_Package::MakePrivatePropertyNameForSerialize('sPurviewProperty',__CLASS__) ;
		
		return $arrParentPropertys ;
	}
	
	/**
	 * 
	 * @access public 
	 * @return bool 
	 * @see JCAT_IIdentity::Active()
	 */
	public function Activing()
	{
		JCAT_ASSERT::ASSERT_NOTNULL($this->sActiveTimeColumnName,JCAT_Language::SentenceEx('尚未设置相关字段，请先调用 SetActiveTimeColumnName() 方法','JCAT',null));
		JCAT_ASSERT::ASSERT_($this->aDBModel->IsDataExists($this->sActiveTimeColumnName),JCAT_Language::SentenceEx('字段表中不存在字段“%s”；请在构造函数中将此字段加入到字段表中。','JCAT',null,$this->sActiveTimeColumnName)) ;
		
		// 更新数据
		$nActiveTime = time() ;
		$this->aDBModel->Set(self::TIME_ACTIVE,$nActiveTime) ;
		$this->aDBModel->Set(self::IP_ACTIVE,$_SERVER['REMOTE_ADDR']) ;
		
		// 保存
		return $this->aDBModel->Save() ;
	}
	
	/**
	 * 
	 * @access public 
	 * @return void 
	 */
	public function SetEncryption( $Encryption=JCAT_Authentication::PASSWORD_MD5 )
	{
		JCAT_ASSERT::ASSERT_ISTHESE($Encryption,array('callback','null'));
		$this->Encryption = $Encryption ;
	}

	/**
	 * 
	 * @access public 
	 * @return callback 
	 */
	public function GetEncryption()
	{
		return $this->Encryption ;
	}
	
	/**
	 * 
	 * @access public 
	 * @return bool 
	 * @see JCAT_IIdentity::IsLogined()
	 */
	public function IsLogined ()
	{
		return $this->bLogined ;
	}
	
	/**
	 * 检查权限
	 * 
	 * @access	public
	 * @param	$nPurviewBit			int			权限位
	 * @param	$sPurviewDomain=null	string		指定权限域
	 * @return	bool
	 */
	public function HasPurview($nPurviewBit,$sPurviewDomain=null)
	{
		$sPurviewProperty = $this->GetPurviewProperty() ;
		if(!$sPurviewProperty)
		{
			return false ;
		}
		
		$aUserModel = $this->GetModel() ;
		if( !$aUserModel )
		{
			return false ;
		}
		
		$aAggPurviewsModel = $aUserModel->GetModel($sPurviewProperty) ;
		if( !$aAggPurviewsModel )
		{
			return false ;
		}
		
		if( !JCAT_Global::HasImplementedTo($aAggPurviewsModel,'JCAT_IAggregationModel') )
		{
			throw new JCAT_Exception(JCAT_Language::SentenceEx(
				'ID对象(%s)的权限模型(Purview Model)必须是一个聚合模型(实现 JCAT_IAggregationModel)'
				, 'JCAT', null, $this->GetIdentityClass()
			)) ;
		}
		
		$aIterator = $aAggPurviewsModel->CreateModelIterator() ;
		for ( $aIterator->First(); !$aIterator->IsDone(); $aIterator->Next() )
		{
			$aPurview = $aIterator->Current() ;
			
			// 检查 权限域
			$sUserPurviewDomain = $aPurview->Get(self::PURVIEW_DOMAIN) ;
			if($sPurviewDomain and $sUserPurviewDomain!=$sPurviewDomain)
			{
				continue ;
			}
			
			$sUserPurviewBit = $aPurview->Get(self::PURVIEW_BIT) ;
			if( $nPurviewBit & $sUserPurviewBit )
			{
				return true ;
			}
		}
		
		return false ;
	}
	
	/**
	 * 
	 * @access public 
	 * @param $sAuthName			string					认证用户名 
	 * @param $sAuthPassword		string					认证用户密码 
	 * @param $aIDMgr=null			JCAT_IdentityManager
	 * @param $bSendMessage=true	bool					是否发送消息 
	 * @return bool 
	 */
	public function Login ( $sAuthName, $sAuthPassword, JCAT_IdentityManager $aIDMgr=null, $bSendMessage=true )
	{
		$aModel = $this->GetModel() ;
		
		// find by user
		$aModel->FindBy(self::AUTH_USERNAME,$sAuthName) ;
		if( $this->aDBModel->Load() )
		{
			// 加密函数
			$EncryptionFunction = $this->GetEncryption() ;
			
			// 使用明文密码
			if ($EncryptionFunction===JCAT_Authentication::PASSWORD_PLAIN)
			{
				$sCipherText =& $sAuthPassword ;
			}
			
			// 用过加密函数计算密文
			else 
			{
				$sCipherText = call_user_func_array($EncryptionFunction,array($sAuthPassword)) ;
			}

			// 比较密文
			if($this->GetAuthPassword() === $sCipherText)
			{
				$this->bLogined = true ;
				
				// 提交到身份管理器
				if(!$aIDMgr)
				{
					$aIDMgr = JCAT_IdentityManager::GetGlobalInstance() ;
				}
				$aIDMgr->IdentityLogin($this) ;
				
				// 产生消息
				if($bSendMessage)
				{
					new JCAT_Message(JCAT_Language::SentenceEx('登录成功。','JCAT',null,$sAuthName),'MSGMVC_OK') ;
				}
			}
			
			else 
			{
				$this->bLogined = false ;
				
				// 产生消息
				if($bSendMessage)
				{
					new JCAT_Message(JCAT_Language::SentenceEx('密码错误，请检查输入是否正确。','JCAT',null),'MSGMVC_BAD') ;
				}				
			}
			
		}
		else
		{
			$this->bLogined = false ;
			
			// 产生消息
			if($bSendMessage)
			{
				new JCAT_Message(JCAT_Language::SentenceEx('用户名：“%s”不存在，请检查是否输入错误。','JCAT',null,$sAuthName),'MSGMVC_BAD') ;
			}
		}
				
		// 返回结果
		return $this->IsLogined() ;
	}
	
	/**
	 * 
	 * @access public 
	 * @return void 
	 */
	public function Logout ()
	{
		$this->bLogined = false ;
	}

	
	/**
	 * 
	 * @access public 
	 * @return bool 
	 * @see JCAT_IIdentity::GetAuthName()
	 */
	public function GetAuthName()
	{
		return $this->aDBModel->Get(self::AUTH_USERNAME) ;
	}
	
	/**
	 * 
	 * @access public 
	 * @return bool 
	 * @see JCAT_IIdentity::GetAuthPassword()
	 */
	public function GetAuthPassword()
	{
		return $this->aDBModel->Get(self::AUTH_PASSWORD) ;
	}
	
	/**
	 * 
	 * @access public 
	 * @return bool 
	 * @see JCAT_IIdentity::GetCreateTime()
	 */
	public function GetCreateTime()
	{
		return $this->aDBModel->Get(self::TIME_CREATE) ;
	}
	
	/**
	 * 
	 * @access public 
	 * @return bool 
	 * @see JCAT_IIdentity::GetLastLoginTime()
	 */
	public function GetLastLoginTime()
	{
		return $this->aDBModel->Get(self::TIME_LASTLOGIN) ;
	}
	
	/**
	 * 
	 * @access public 
	 * @return bool 
	 * @see JCAT_IIdentity::GetActiveTime()
	 */
	public function GetActiveTime()
	{
		return $this->aDBModel->Get(self::TIME_ACTIVE) ;
	}
	
	/**
	 * 
	 * @access public 
	 * @return bool 
	 * @see JCAT_IIdentity::GetLastLoginIP()
	 */
	public function GetLastLoginIP()
	{
		return $this->aDBModel->Get(self::IP_LASTLOGIN) ;
	}
	
	/**
	 * 
	 * @access public 
	 * @return bool 
	 * @see JCAT_IIdentity::GetLastLoginIP()
	 */
	public function GetActiveIP()
	{
		return $this->aDBModel->Get(self::IP_ACTIVE) ;
	}
	
	/**
	 * 设置对象属性 sPurviewProperty
	 *
	 * @access	public
	 * @param	$sPurviewProperty		string	sPurviewProperty
	 * @return	void
	 */
	public function SetPurviewProperty($sPurviewProperty=null)
	{
		$this->sPurviewProperty = $sPurviewProperty ;
	}
	
	/**
	 * 取得对象属性 sPurviewProperty
	 *
	 * @access	public
	 * @return	string
	 */
	public function GetPurviewProperty()
	{
		return $this->sPurviewProperty ;
	}


	// 属性 /////////////////////////////////////////////////////
	
	/**
	 * 数据库模型
	 * 
	 * @access	private
	 * @var		JCAT_IDBModel
	 */
	private $aDBModel ;
	
	/**
	 * 记录是否已经的登录 
	 * 
	 * @access	private
	 * @var		bool
	 */
	private $bLogined = false ;
		
	/**
	 * 认证用户名 字段名 
	 * @access	const
	 * @var		string
	 */
	const AUTH_USERNAME = 'sAuthUsername' ;
	
	/**
	 * 认证密码 字段名 
	 * 
	 * @access	const
	 * @var		string
	 */
	const AUTH_PASSWORD = 'sAuthPassword' ;

	/**
	 * 帐号创建时间 字段名 
	 * 
	 * @access	const
	 * @var		string
	 */
	const TIME_CREATE = 'nTimeCreate' ;

	/**
	 * 最近登录时间 字段名 
	 * 
	 * @access	const
	 * @var		string
	 */
	const TIME_LASTLOGIN = 'nTimeLastLogin' ;
	
	/**
	 * 最近活动时间 字段名 
	 * 
	 * @access	const
	 * @var		string
	 */
	const TIME_ACTIVE = 'sTimeActive' ;

	/**
	 * 最近登录IP 字段名 
	 * 
	 * @access	const
	 * @var		string
	 */
	const IP_LASTLOGIN = 'sIpLastLogin' ;

	/**
	 * 活动IP 字段名 
	 * 
	 * @access	const
	 * @var		string
	 */
	const IP_ACTIVE = 'sIpActive' ;
	
	
	/**
	 * 权限 字段名 
	 * 
	 * @access	const
	 * @var		string
	 */
	const PURVIEW_DOMAIN = 'sPurviewDomain' ;
	
	/**
	 * 权限位 字段名 
	 * 
	 * @access	const
	 * @var		string
	 */
	const PURVIEW_BIT = 'nPurviewBit' ;
	
	
	
	/**
	 * 对密码加密的 回调函数
	 * 
	 * @access	private
	 * @var		callback
	 */
	private $Encryption = JCAT_Authentication::PASSWORD_MD5 ;
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @var		string
	 */
	private $sPurviewProperty ;

}
?>
